package org.apache.cordova.plugin;

import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.w3c.dom.Document;
import org.w3c.dom.DOMException;

// For write operation
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringReader;
import java.io.*;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
 * This class echoes a string called from JavaScript.
 */
public class XSLT extends CordovaPlugin {
    static Document document;
    @Override
    public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
        //final JSONArray fargs = args;
        if (action.equals("transform")) {
            cordova.getThreadPool().execute(new Runnable() {
                public void run() {
                    try {
                        String xslts = args.getString(0);
                        String xmls  = args.getString(1);
                        transform(xslts, xmls, document, callbackContext);
                    } catch (JSONException e) {
                        callbackContext.error("Got error while read param " + e);
                    }
                }
            });
            return true;
        }
        return false;
    }

    private void transform(String xslts, String xmls, Document document, CallbackContext callbackContext) {
        /*if (args.length != 3) {
            callbackContext.error("Args must be: [host, port, text]");
        }*/
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            document = builder.parse(new InputSource(new StringReader(xmls)));

            // Use a Transformer for output
            TransformerFactory tFactory = TransformerFactory.newInstance();
            StreamSource stylesource = new StreamSource(new StringReader(xslts));
            Transformer transformer = tFactory.newTransformer(stylesource);
            DOMSource source = new DOMSource(document);
            
            StringWriter sw = new StringWriter();
            StreamResult result = new StreamResult(sw);
            //StreamResult result = new StreamResult(System.out);
            transformer.transform(source, result);
            StringBuffer sb = sw.getBuffer(); 
            String output = sb.toString(); 
            callbackContext.success(output);
        } catch (TransformerConfigurationException tce) {
            // Error generated by the parser

            // Use the contained exception, if any
            Throwable x = tce;

            if (tce.getException() != null) {
                x = tce.getException();
            }
            StringWriter sw = new StringWriter();
            x.printStackTrace(new PrintWriter(sw));
            String exceptionAsString = sw.toString();
            callbackContext.error("\n** Transformer Factory error" + tce.getMessage() + "\nGot trace:\n"+exceptionAsString);

        } catch (TransformerException te) {
            // Error generated by the parser
            // Use the contained exception, if any
            Throwable x = te;

            if (te.getException() != null) {
                x = te.getException();
            }
            StringWriter sw = new StringWriter();
            x.printStackTrace(new PrintWriter(sw));
            String exceptionAsString = sw.toString();
            callbackContext.error("\n** Transformation error" + te.getMessage() + "\nGot trace:\n"+exceptionAsString);

        } catch (SAXException sxe) {
            // Error generated by this application
            // (or a parser-initialization error)
            Exception x = sxe;

            if (sxe.getException() != null) {
                x = sxe.getException();
            }
            StringWriter sw = new StringWriter();
            x.printStackTrace(new PrintWriter(sw));
            String exceptionAsString = sw.toString();
            callbackContext.error("\n**maybe parser-initialization\nGot trace:\n"+exceptionAsString);

        } catch (ParserConfigurationException pce) {
            // Parser with specified options can't be built
            StringWriter sw = new StringWriter();
            pce.printStackTrace(new PrintWriter(sw));
            String exceptionAsString = sw.toString();
            callbackContext.error("\n**Parser with specified options can't be built\nGot trace:\n"+exceptionAsString);
        } catch (IOException ioe) {
            // I/O error
            StringWriter sw = new StringWriter();
            ioe.printStackTrace(new PrintWriter(sw));
            String exceptionAsString = sw.toString();
            callbackContext.error("\n**I/O error\nGot trace:\n"+exceptionAsString);
        }
    }
}
